package com.zzl.bonds.ticket.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zzl.bonds.ticket.constant.FileBucketTypeConstant;
import com.zzl.bonds.ticket.constant.StringConstant;
import com.zzl.bonds.ticket.constant.type.DataTypeEnum;
import com.zzl.bonds.ticket.constant.type.InvoiceTypeEnum;
import com.zzl.bonds.ticket.dao.TicketDataDao;
import com.zzl.bonds.ticket.dto.TicketDataDto;
import com.zzl.bonds.ticket.dto.TicketDataTransferAddDto;
import com.zzl.bonds.ticket.entity.TicketDataEntity;
import com.zzl.bonds.ticket.feign.FileCenterFeign;
import com.zzl.bonds.ticket.service.TicketDataService;
import com.zzl.bonds.ticket.untils.DateUtils;
import com.zzl.general.common.exception.SysException;
import com.zzl.general.common.serurity.entity.User;
import com.zzl.general.common.utils.PageUtils;
import com.zzl.general.common.utils.Query;
import com.zzl.general.common.utils.UuidUtils;
import com.zzl.general.ocr.BdAiUntil;
import com.zzl.general.ocr.constant.InvoiceFileTypeEnum;
import com.zzl.general.ocr.pojo.InvoiceVerParam;
import com.zzl.general.ocr.pojo.InvoiceVerificationInfo;
import com.zzl.general.ocr.pojo.InvoiceWordsResult;
import feign.Response;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 开立或转让上传的资料
 *
 * @author sunpp
 * @date 2022-02-16 11:14:06
 */
@Slf4j
@Service("ticketDataService")
public class TicketDataServiceImpl extends ServiceImpl<TicketDataDao, TicketDataEntity> implements TicketDataService {


    @Autowired
    private BdAiUntil bdAiUntil;

    @Autowired
    private FileCenterFeign fileCenterFeign;

    /**
     * 通过票的id查 相关附件
     *
     * @param id
     * @return 附件集合
     */
    @Override
    public List<TicketDataEntity> getByTicketId(String id, Integer type) {
        QueryWrapper<TicketDataEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(TicketDataEntity::getTicketActionId, id)
                .eq(TicketDataEntity::getTicketActionType, type);
        return this.list(queryWrapper);
    }

    /**
     * 分页查询
     *
     * @param params 查询参数
     * @return 分页数据
     */
    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<TicketDataEntity> page = this.page(
                new Query<TicketDataEntity>().getPage(params),
                new QueryWrapper<>()
        );

        return new PageUtils(page);
    }

    /**
     * 新增
     *
     * @param dataList 新增实体
     * @param user     当前登录用户
     * @throws SysException 业务异常
     */
    @Override
    public void saveTicketData(List<TicketDataDto> dataList, User user) throws SysException {
        if (CollectionUtils.isEmpty(dataList)) {
            return;
        }
        log.info("开立附件保存，入参：", JSON.toJSONString(dataList));
        List<TicketDataDto> invoiceList = dataList.stream().filter(x -> x.getDataType().equals(DataTypeEnum.INVOICE.getCode())).collect(Collectors.toList());
        if (!CollectionUtils.isEmpty(invoiceList)) {
            for (TicketDataDto dataDto : invoiceList) {
                if (ObjectUtils.isEmpty(dataDto.getInvoiceNo())) {
                    throw new SysException("发票编号不能为空");
                }
            }
            // 校验 发票信息的唯一性
            List<String> dataNos = invoiceList.stream().map(TicketDataDto::getInvoiceNo).collect(Collectors.toList());
            QueryWrapper<TicketDataEntity> queryWrapper = new QueryWrapper<>();
            queryWrapper.lambda().in(TicketDataEntity::getDataNo, dataNos);
            List<TicketDataEntity> list = this.list(queryWrapper);
            if (!CollectionUtils.isEmpty(list)) {
                throw new SysException("发票编号" + list.get(0).getDataNo() + "重复");
            }
        }
        // ocr 识别发票的全量信息 并验证发票编号的真实性 1. 先下载  2.在读取
        List<TicketDataEntity> entities = new ArrayList<>();
        for (TicketDataDto dataDto : dataList) {
            TicketDataEntity entity = new TicketDataEntity();
            entity.setId(UuidUtils.UUID());
            BeanUtils.copyProperties(dataDto, entity);
            if (DataTypeEnum.INVOICE.getCode().equals(dataDto.getDataType())) {
                invoiceValidation(dataDto);
            }
            entity.setCreatorId(user.getId());
            entity.setOrgId(user.getOrgId());
            entity.setEnterpriseId(user.getEnterpriseId());
            entities.add(entity);
        }
        this.saveBatch(entities);
    }

    @Override
    public List<TicketDataEntity> getByTicketIdAndType(String id, Integer type) {
        QueryWrapper<TicketDataEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(TicketDataEntity::getTicketActionId, id)
                .eq(TicketDataEntity::getTicketActionType, type);
        return this.list(queryWrapper);
    }

    @Override
    public void saveTicketTransferData(List<TicketDataTransferAddDto> dataList, User user) throws SysException {
        if (CollectionUtils.isEmpty(dataList)) {
            return;
        }
        log.info("开立附件保存，入参：", JSON.toJSONString(dataList));
        List<TicketDataTransferAddDto> invoiceList = dataList.stream().filter(x -> x.getDataType().equals(DataTypeEnum.INVOICE.getCode())).collect(Collectors.toList());
        if (!CollectionUtils.isEmpty(invoiceList)) {
            for (TicketDataTransferAddDto dataDto : invoiceList) {
                if (dataDto.getDataType().equals(DataTypeEnum.INVOICE.getCode())&&ObjectUtils.isEmpty(dataDto.getInvoiceNo())) {
                    throw new SysException("发票编号不能为空");
                }
            }
            // 校验 发票信息的唯一性
            List<String> dataNos = invoiceList.stream().map(TicketDataTransferAddDto::getDataNo).collect(Collectors.toList());
            QueryWrapper<TicketDataEntity> queryWrapper = new QueryWrapper<>();
            queryWrapper.lambda().in(TicketDataEntity::getDataNo, dataNos);
            List<TicketDataEntity> list = this.list(queryWrapper);
            if (!CollectionUtils.isEmpty(list)) {
                throw new SysException("发票编号" + list.get(0).getDataNo() + "重复");
            }
        }
        // ocr 识别发票的全量信息 并验证发票编号的真实性 1. 先下载  2.在读取

        List<TicketDataEntity> entities = new ArrayList<>();
        for (TicketDataTransferAddDto dataDto : dataList) {
            TicketDataEntity entity = new TicketDataEntity();
            entity.setId(UuidUtils.UUID());
            BeanUtils.copyProperties(dataDto, entity);
            if (DataTypeEnum.INVOICE.getCode().equals(dataDto.getDataType())) {
//                InvoiceWordsResult invoiceWordsResult = ocrInvoice(dataDto.getDataAddress(), dataDto.getFileName());
//                if (ObjectUtils.isEmpty(invoiceWordsResult)) {
//                    throw new SysException("未识别发票文件" + dataDto.getDataNo());
//                }
                // todo 测试先关闭
               /* if (!dataDto.getDataNo().equals(invoiceWordsResult.getInvoiceNum())) {
                    throw new SysException("填写发票编号与发票真实编号不一致,填写编号：" + dataDto.getDataNo());
                }*/
//                entity.setRemark(JSON.toJSONString(invoiceWordsResult));
            }
            entity.setCreatorId(user.getId());
            entity.setOrgId(user.getOrgId());
            entity.setEnterpriseId(user.getEnterpriseId());
            entities.add(entity);
        }
        this.saveBatch(entities);

    }

    /**
     * 发票验真假
     *
     * @param dataDto 发票信息
     * @throws SysException 异常
     */
    private void invoiceValidation(TicketDataDto dataDto) throws SysException {
        if (DataTypeEnum.INVOICE.getCode().equals(dataDto.getDataType())) {
            InvoiceVerParam invoiceVerParam = new InvoiceVerParam();
            invoiceVerParam.setInvoiceCode(dataDto.getInvoiceCode());
            invoiceVerParam.setInvoiceDate(DateUtils.dateFormat(dataDto.getBillingDate(), DateUtils.DF_YYYY_MM_DD));
            invoiceVerParam.setInvoiceNum(dataDto.getInvoiceNo());
//                发票类型 0 专票 1普票
            invoiceVerParam.setInvoiceType(InvoiceTypeEnum.getType(dataDto.getInvoiceType()));
            invoiceVerParam.setCheckCode(dataDto.getLastSixDigitsCheckCode());
            invoiceVerParam.setTotalAmount(dataDto.getAmountIncludingTax()+"");
            InvoiceVerificationInfo invoiceVerificationInfo = null;
            try {
                //todo 发票验证接口异常，暂时注释
//                invoiceVerificationInfo = bdAiUntil.invoiceValidation(invoiceVerParam);
            } catch (Exception e) {
                throw new SysException("发票验真失败");
            }
        }
    }

    /**
     * 识别发票 ocr
     *
     * @param objId 文件地址 id
     * @return 发票信息
     * @throws SysException 系统异常
     */
    private InvoiceWordsResult ocrInvoice(String objId, String fileName) throws SysException {
        try {
            Response response = fileCenterFeign.downloadFileMongoAllowAuth(objId, FileBucketTypeConstant.FILE_BUCKET_OPEN_RELATED_FILE.getKey());
            InvoiceFileTypeEnum invoiceFileTypeEnum;
            if (fileName.endsWith(StringConstant.PDF)) {
                invoiceFileTypeEnum = InvoiceFileTypeEnum.PDF_FILE;
            } else {
                invoiceFileTypeEnum = InvoiceFileTypeEnum.IMAGE;
            }
            return bdAiUntil.invoiceIdentify(response.body().asInputStream(), invoiceFileTypeEnum);
        } catch (Exception e) {
            throw new SysException("识别发票文件异常");
        }
    }


}